package com.fsserver.common.utils;

import org.slf4j.MDC;
import org.springframework.util.StringUtils;

import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;

/**
 * MDC工具类，用于管理日志链路追踪的traceId
 * 
 * @author fsserver
 * @date 2025-03-13
 */
public final class MDCTraceUtils {
    /**
     * TraceId标识
     */
    public static final String TRACE_ID_KEY = "traceId";
    
    /**
     * 业务ID标识
     */
    public static final String BUSINESS_ID_KEY = "businessId";
    
    /**
     * 用户ID的键名
     */
    public static final String USER_ID_KEY = "userId";
    
    /**
     * 请求开始时间
     */
    public static final String REQUEST_START_TIME_KEY = "requestStartTime";
    
    /**
     * 请求路径
     */
    public static final String REQUEST_PATH_KEY = "requestPath";
    
    /**
     * 私有构造函数，防止实例化
     */
    private MDCTraceUtils() {
        throw new IllegalStateException("Utility class");
    }
    
    /**
     * 生成TraceId
     * 使用更高效的方式生成唯一ID
     * 
     * @return 新的TraceId
     */
    public static String generateTraceId() {
        // 使用时间戳+随机数的方式生成，比UUID更高效
        long timestamp = System.currentTimeMillis();
        int random = ThreadLocalRandom.current().nextInt(1000000);
        return Long.toHexString(timestamp) + Integer.toHexString(random);
    }
    
    /**
     * 获取当前的TraceId
     * 
     * @return 当前TraceId，如果不存在则返回null
     */
    public static String getTraceId() {
        return MDC.get(TRACE_ID_KEY);
    }
    
    /**
     * 设置TraceId
     * 
     * @param traceId 要设置的TraceId
     */
    public static void setTraceId(String traceId) {
        if (StringUtils.hasText(traceId)) {
            MDC.put(TRACE_ID_KEY, traceId);
        }
    }
    
    /**
     * 设置业务ID
     * 
     * @param businessId 业务ID
     */
    public static void setBusinessId(String businessId) {
        if (StringUtils.hasText(businessId)) {
            MDC.put(BUSINESS_ID_KEY, businessId);
        }
    }
    
    /**
     * 获取业务ID
     * 
     * @return 当前业务ID，如果不存在则返回null
     */
    public static String getBusinessId() {
        return MDC.get(BUSINESS_ID_KEY);
    }
    
    /**
     * 设置用户ID
     * 
     * @param userId 用户ID
     */
    public static void setUserId(String userId) {
        if (StringUtils.hasText(userId)) {
            MDC.put(USER_ID_KEY, userId);
        }
    }
    
    /**
     * 获取用户ID
     * 
     * @return 当前用户ID，如果不存在则返回null
     */
    public static String getUserId() {
        return MDC.get(USER_ID_KEY);
    }
    
    /**
     * 设置请求开始时间
     * 
     * @param startTime 请求开始时间
     */
    public static void setRequestStartTime(long startTime) {
        MDC.put(REQUEST_START_TIME_KEY, String.valueOf(startTime));
    }
    
    /**
     * 获取请求开始时间
     * 
     * @return 请求开始时间，如果不存在则返回-1
     */
    public static long getRequestStartTime() {
        String startTime = MDC.get(REQUEST_START_TIME_KEY);
        return StringUtils.hasText(startTime) ? Long.parseLong(startTime) : -1L;
    }
    
    /**
     * 设置请求路径
     * 
     * @param path 请求路径
     */
    public static void setRequestPath(String path) {
        if (StringUtils.hasText(path)) {
            MDC.put(REQUEST_PATH_KEY, path);
        }
    }
    
    /**
     * 获取请求路径
     * 
     * @return 请求路径，如果不存在则返回null
     */
    public static String getRequestPath() {
        return MDC.get(REQUEST_PATH_KEY);
    }
    
    /**
     * 初始化TraceId
     * 如果当前MDC中已存在traceId则使用现有的，否则生成新的
     * 
     * @return 使用的TraceId
     */
    public static String initTraceId() {
        String traceId = getTraceId();
        if (!StringUtils.hasText(traceId)) {
            traceId = generateTraceId();
            setTraceId(traceId);
        }
        return traceId;
    }
    
    /**
     * 清除MDC中的所有数据
     */
    public static void clear() {
        MDC.clear();
    }
    
    /**
     * 清除MDC中的指定键
     * 
     * @param key 要清除的键
     */
    public static void remove(String key) {
        if (StringUtils.hasText(key)) {
            MDC.remove(key);
        }
    }
} 